home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#42 (Mar 89)
/
calc source
/
Parser.c
< prev
next >
Wrap
Text File
|
1989-02-09
|
8KB
|
380 lines
#include <WindowMgr.h>
#include <ListMgr.h>
#include <OSUtil.h>
#include <EventMgr.h>
#include <Strings.h>
#include <Math.h>
#include <Ctype.h>
#include <Stdio.h>
#include "MacCalc.h"
#include "CalcData.h"
#include "Parser.h"
unsigned char *curr_pos = NULL ;
int parse_err = 0 ;
Str255 buffer ;
/* Simple algabraic expression parser */
double ParseFormula( formula, error )
unsigned char *formula ;
int *error ;
{
register double value ;
/* convert into c string in buffer */
BlockMove( &formula[2], buffer, formula[0]-1 ) ;
buffer[formula[0]-1] = 0 ; /* 0 terminate buffer */
curr_pos = buffer ;
parse_err = 0 ;
value = ParseExpression( ) ;
*error = parse_err ; /* Set error flag */
return ( value ) ;
}
double ParseExpression( )
{
register double val ;
val = ParseFactor( ) ;
switch( *curr_pos ) {
case '+':
curr_pos++ ;
val += ParseExpression( ) ;
break ;
case '-':
curr_pos++ ;
val -= ParseExpression( ) ;
break ;
case '*':
curr_pos++ ;
val *= ParseExpression( ) ;
break ;
case '/':
curr_pos++ ;
val /= ParseExpression( ) ;
break ;
}
return val ;
}
double ParseFactor( )
{
register double val = 0 ;
register double val2 ;
register int has_sign = FALSE ;
if( *curr_pos == '-' ) {
has_sign = TRUE ;
curr_pos++ ;
}
if( *curr_pos != '(' ) {
/* determine whether this is an address or not */
if( IsDigit( *curr_pos ) || *curr_pos == '.' ) {
val = ParseValue( ) ;
}else{
if( IsFunction( ) ) {
val = CallFunction( ) ;
}else{
val = ParseAddress( ) ;
}
}
switch( *curr_pos ) {
case '^':
curr_pos++ ;
val2 = ParseFactor( ) ;
val = pow( val, val2 ) ;
break ;
case '*':
curr_pos++ ;
val2 = ParseFactor( ) ;
val *= val2 ;
break ;
case '/':
curr_pos++ ;
val2 = ParseFactor( ) ;
val /= val2 ;
break ;
}
}else{
curr_pos++ ;
val = ParseExpression( ) ;
if( *curr_pos == ')' ) {
curr_pos++ ;
}else{
parse_err = MISMATCHED_PARENTHESIS ;
}
}
return ( has_sign ? -( val ):val ) ;
}
double ParseValue( )
{
register double val = 0 ;
if( IsDigit( *curr_pos ) || ( *curr_pos == '.' ) ) {
val = atof( ) ;
}else{
parse_err = INVALID_NUMBER ;
}
return val ;
}
double ParseAddress( )
{
register int row ;
register int column ;
register double val = 0 ;
column = GetColumn( ) ;
row = GetRow( ) ;
if( ( row > MAX_ROWS ) || ( column > MAX_COLUMNS ) ) {
parse_err = ADDRESS_TOO_LARGE ;
}else{
val = curr_sheet_ptr->sheet_data[row-1][column-1].value ;
}
return val ;
}
int GetRow( )
{
register int row ;
if( IsDigit( *curr_pos ) ) {
row = *curr_pos - '0' ;
}else{
parse_err = INVALID_ADDRESS ;
}
curr_pos++ ;
return row ;
}
int GetColumn( )
{
register int column ;
if( IsAlpha( *curr_pos ) ) {
if( *curr_pos >= 'a' ) {
column = ( *curr_pos - 'a' ) + 1 ;
}else{
column = ( *curr_pos - 'A' ) + 1 ;
}
}else{
parse_err = INVALID_ADDRESS ;
}
curr_pos++ ;
return column ;
}
int IsFunction( )
{
register unsigned char *p ;
p = curr_pos ;
while( IsAlpha( *p ) || IsDigit( *p ) ) {
p++ ;
}
return ( *p == '(' ) ? TRUE:FALSE ;
}
double CallFunction( )
{
unsigned char fun_name[32] ;
register unsigned char *p ;
register int fun_number ;
register double value ;
register ARG_PTR args ;
p = fun_name ;
while( IsAlpha( *curr_pos ) || IsDigit( *curr_pos ) ) {
*p = toupper( *curr_pos ) ;
p++; curr_pos++;
}
*p = '\0' ;
curr_pos++ ;
args = BuildArg( ) ;
if( ( fun_number = Lookup( fun_name ) ) > -1 ) {
value = (*fun_table[fun_number].fun_ptr)( args ) ;
}else{
parse_err = INVALID_FUNCTION ;
}
DestroyArgs( args ) ;
return value ;
}
int Lookup( fun_name )
unsigned char *fun_name ;
{
register int i = 0 ;
while( fun_table[i].fun_name[0] != 0 ) {
if( !strcmp( fun_name, fun_table[i].fun_name ) ) {
return i ;
}
i++ ;
}
return -1 ;
}
ARG_PTR BuildArg( )
{
int error ;
ARG_PTR first_arg_ptr = NULL, last_arg_ptr = NULL, next_arg_ptr = NULL ;
/* This needs to be changed so that recursive functions calls can be
made */
while( *curr_pos != ')' ) {
next_arg_ptr = GetArg( ) ;
next_arg_ptr->value = ParseExpression( ) ;
next_arg_ptr->type = VALUE_ARG ;
if( *curr_pos == ',' ) {
curr_pos++ ;
}
if( last_arg_ptr != NULL ) {
last_arg_ptr->next_arg = next_arg_ptr ;
}
if( first_arg_ptr == NULL ) {
first_arg_ptr = next_arg_ptr ;
}
last_arg_ptr = next_arg_ptr ;
}
next_arg_ptr->next_arg = NULL ;
/* Now pass the last parenthesis by */
if( *curr_pos == ')' ) {
curr_pos++ ;
return first_arg_ptr ;
}else{
parse_err = MISMATCHED_PARENTHESIS ;
return NULL ;
}
}
double atof( )
{
register double val = 0.0 ;
register double val2 = 0.0 ;
if( IsDigit( *curr_pos ) || ( *curr_pos == '.' ) ) {
while( *curr_pos && IsDigit( *curr_pos ) ) {
val = ( val * 10 ) + ( *curr_pos - '0' ) ;
curr_pos++ ;
}
if( *curr_pos == '.' ) {
curr_pos++ ;
}
while( *curr_pos && IsDigit( *curr_pos ) ) {
val2 = ( val2 * 10 ) + ( *curr_pos - '0' ) ;
curr_pos++ ;
}
if( val2 != 0.0 ) {
while( val2 > 1 ) {
val2 /= 10 ;
}
}
val += val2 ;
}else{
parse_err = INVALID_NUMBER ;
}
return val ;
}
void ftoa( val, buffer )
double val ;
unsigned char *buffer ;
{
long whole ;
Str255 buff ;
Str255 tmp ;
int has_sign ;
int prec = /*curr_precision*/5 ;
has_sign = ( val < 0 ) ? TRUE:FALSE ;
val = ( val<0 ) ? -val:val ; /* <- */
whole = val/1 ;
NumToString( whole, buffer ) ;
/* convert into c string in buffer */
BlockMove( &buffer[1], buff, buffer[0] ) ;
buff[buffer[0]] = 0 ; /* 0 terminate buffer */
val -= whole ;
if( prec ) {
do{
val *= 10.0 ;
}while( --prec ) ;
whole = val ;
NumToString( whole, buffer ) ;
/* convert into c string in buffer */
BlockMove( &buffer[1], tmp, buffer[0] ) ;
tmp[buffer[0]] = 0 ; /* 0 terminate buffer */
strcat( buff, "." ) ;
strcat( buff, tmp ) ;
}
if( has_sign ) {
tmp[0] = '-' ;
tmp[1] = '\0' ;
strcat( tmp, buff ) ;
strcpy( &buffer[1], tmp ) ;
buffer[0] = strlen( tmp ) ;
}else{
strcpy( &buffer[1], buff ) ;
buffer[0] = strlen( buff ) ;
}
return ;
}
double GetFloat( formula, error )
unsigned char *formula ;
int *error ;
{
register double value ;
/* convert into c string in buffer */
BlockMove( &formula[1], buffer, formula[0] ) ;
buffer[formula[0]] = 0 ; /* 0 terminate buffer */
curr_pos = buffer ;
parse_err = 0 ;
value = atof( ) ;
*error = parse_err ; /* Set error flag */
return ( value ) ;
}
ARG_PTR GetArg( )
{
register int i ;
for( i=0;i<30;i++){
if( arg_free_pool[i].in_use == FREE_ARG ) {
arg_free_pool[i].in_use = IN_USE ;
return &arg_free_pool[i] ;
}
}
return NULL ;
}
void DestroyArgs( arg_ptr )
ARG_PTR arg_ptr ;
{
if( arg_ptr != NULL ) {
PutArg( arg_ptr ) ;
while( arg_ptr->next_arg != NULL ) {
arg_ptr = arg_ptr->next_arg ;
PutArg( arg_ptr ) ;
}
}
return ;
}
void PutArg( arg_ptr )
ARG_PTR arg_ptr ;
{
arg_ptr->in_use = FREE_ARG ;
return ;
}